﻿//----------------------------------------------------------------
// Copyright (C) 2011-2012 TaoSys软件有限责任公司
// All rights reserved.
//
// 文件名：SymmetricEncryption.cs
// 摘  要：对称加密类
// 说  明：提供了DES,RC2,Rijndael,TripleDES对称加密算法
//

//当前版本 ：1.0
//作   者 ：陶剑扬
//完成日期 ：2011-06-23
//----------------------------------------------------------------
//密钥IV大小说明（bit）
/*
	DES:
		MaxSize: 64
		MinSize: 64
		SkipSize: 0
        IV: 64
	RC2:
		MaxSize: 128
		MinSize: 40
		SkipSize: 8
        IV: 64
	Rijndael:
		MaxSize: 256
		MinSize: 128
		SkipSize: 64
        IV: 128
	TripleDES:
		MaxSize: 192
		MinSize: 128
		SkipSize: 64
        IV: 64
 */

using System;
using System.IO;
using System.Text;
using System.Linq;
using System.Collections.Generic;
using System.Security.Cryptography;


namespace PowerSys.SystemFramework.Cryptography
{
    public class SymmetricEncryption
    {
        #region 常量定义

        //默认Key
        private const string KEY_DES = "$ty@(&!=";
        private const string KEY_RC2 = "$ty@(&!==179xkJ$";
        private const string KEY_RIJNDAEL = "$ty@(&!==179xkJ$$Jkx(&!==179xkJ$";
        private const string KEY_TRIPLEDES = "$ty@(&!==179xkJ$$Jkx(&!=";

        //默认IV
        private const string IV_DEFAULT = "fT@RetST";
        private const string IV_DEFAULT16 = "fT@RetST@82%#H&^";

        #endregion

        #region 变量定义

        private SymmetricEncryptionType mEncryptionType;			//类型
        private string mKey;                                        //密钥
        private string mIV;                                         //初始化向量
        private string mOriginalString;							    //原始串
        private string mEncryptedString;						    //加密串
        private SymmetricAlgorithm mSymmetricAlgorithm;				//对称算法

        #endregion

        #region 枚举

        public enum SymmetricEncryptionType
        {
            DES,
            RC2,
            Rijndael,
            TripleDES
        }

        #endregion

        #region "构造"
        public SymmetricEncryption()
        {
            mEncryptionType = SymmetricEncryptionType.DES;

            this.SetEncryptor();
        }

        public SymmetricEncryption(SymmetricEncryptionType encryptionType)
        {
            mEncryptionType = encryptionType;

            this.SetEncryptor();
        }

        public SymmetricEncryption(SymmetricEncryptionType encryptionType, string originalString)
        {
            mEncryptionType = encryptionType;
            mOriginalString = originalString;

            this.SetEncryptor();
        }
        #endregion

        #region "Public Properties"
        public SymmetricEncryptionType EncryptionType
        {
            get
            {
                return mEncryptionType;
            }
            set
            {
                if (mEncryptionType != value)
                {
                    mEncryptionType = value;
                    mOriginalString = String.Empty;
                    mEncryptedString = String.Empty;

                    this.SetEncryptor();
                }
            }
        }

        public SymmetricAlgorithm CryptoProvider
        {
            get
            {
                return mSymmetricAlgorithm;
            }
            set
            {
                mSymmetricAlgorithm = value;
            }
        }

        public string OriginalString
        {
            get
            {
                return mOriginalString;
            }
            set
            {
                mOriginalString = value;
            }
        }

        public string EncryptedString
        {
            get
            {
                return mEncryptedString;
            }
            set
            {
                mEncryptedString = value;
            }
        }

        /*
        public byte[] key
        {
            get
            {
                return mSymmetricAlgorithm.Key;
            }
            set
            {
                mSymmetricAlgorithm.Key = value;
            }
        }
        */

        public string KeyString
        {
            get
            {
                //return Convert.ToBase64String(mSymmetricAlgorithm.Key);
                return mKey;
            }
            set
            {
                //mSymmetricAlgorithm.Key = Encoding.UTF8.GetBytes(value);
                mKey = value;
                mSymmetricAlgorithm.Key = Encoding.UTF8.GetBytes(mKey);
            }
        }

        /*
        public byte[] IV
        {
            get
            {
                return mSymmetricAlgorithm.IV;
            }
            set
            {
                mSymmetricAlgorithm.IV = value;
            }
        }
        */

        public string IVString
        {
            get
            {
                //return Convert.ToBase64String(mSymmetricAlgorithm.IV);
                return mIV;
            }
            set
            {
                //mSymmetricAlgorithm.IV = Encoding.UTF8.GetBytes(value);
                mIV = value;
                mSymmetricAlgorithm.IV = Encoding.UTF8.GetBytes(mIV);
            }
        }
        #endregion

        #region "Encrypt() Methods"

        public string Encrypt()
        {
            ICryptoTransform ct;
            MemoryStream ms;
            CryptoStream cs;
            byte[] byt;

            ct = mSymmetricAlgorithm.CreateEncryptor(mSymmetricAlgorithm.Key, mSymmetricAlgorithm.IV);

            byt = Encoding.UTF8.GetBytes(mOriginalString);

            ms = new MemoryStream();
            cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
            cs.Write(byt, 0, byt.Length);
            cs.FlushFinalBlock();
            cs.Close();

            mEncryptedString = Convert.ToBase64String(ms.ToArray());

            return mEncryptedString;
        }

        public string Encrypt(string originalString)
        {
            mOriginalString = originalString;

            return this.Encrypt();
        }

        public string Encrypt(string originalString, SymmetricEncryptionType encryptionType)
        {
            mOriginalString = originalString;
            mEncryptionType = encryptionType;

            return this.Encrypt();
        }

        #endregion

        #region "Decrypt() Methods"

        public string Decrypt()
        {
            ICryptoTransform ct;
            MemoryStream ms;
            CryptoStream cs;
            byte[] byt;

            ct = mSymmetricAlgorithm.CreateDecryptor(mSymmetricAlgorithm.Key, mSymmetricAlgorithm.IV);

            byt = Convert.FromBase64String(mEncryptedString);

            ms = new MemoryStream();
            cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
            cs.Write(byt, 0, byt.Length);
            cs.FlushFinalBlock();
            cs.Close();

            mOriginalString = Encoding.UTF8.GetString(ms.ToArray());

            return mOriginalString;
        }

        public string Decrypt(string encryptedString)
        {
            mEncryptedString = encryptedString;

            return this.Decrypt();
        }

        public string Decrypt(string encryptedString, SymmetricEncryptionType encryptionType)
        {
            mEncryptedString = encryptedString;
            mEncryptionType = encryptionType;

            return this.Decrypt();
        }

        #endregion

        #region "SetEncryptor() Method"

        private void SetEncryptor()
        {
            switch (mEncryptionType)
            {
                case SymmetricEncryptionType.DES:
                    mSymmetricAlgorithm = new DESCryptoServiceProvider();
                    mKey = KEY_DES;
                    mSymmetricAlgorithm.Key = Encoding.UTF8.GetBytes(KEY_DES);
                    mSymmetricAlgorithm.IV = Encoding.UTF8.GetBytes(IV_DEFAULT);
                    break;
                case SymmetricEncryptionType.RC2:
                    mSymmetricAlgorithm = new RC2CryptoServiceProvider();
                    mKey = KEY_RC2;
                    mSymmetricAlgorithm.Key = Encoding.UTF8.GetBytes(KEY_RC2);
                    mSymmetricAlgorithm.IV = Encoding.UTF8.GetBytes(IV_DEFAULT);
                    break;
                case SymmetricEncryptionType.Rijndael:
                    mSymmetricAlgorithm = new RijndaelManaged();
                    mKey = KEY_RIJNDAEL;
                    mSymmetricAlgorithm.Key = Encoding.UTF8.GetBytes(KEY_RIJNDAEL);
                    mSymmetricAlgorithm.IV = Encoding.UTF8.GetBytes(IV_DEFAULT16);
                    break;
                case SymmetricEncryptionType.TripleDES:
                    mSymmetricAlgorithm = new TripleDESCryptoServiceProvider();
                    mKey = KEY_TRIPLEDES;
                    mSymmetricAlgorithm.Key = Encoding.UTF8.GetBytes(KEY_TRIPLEDES);
                    mSymmetricAlgorithm.IV = Encoding.UTF8.GetBytes(IV_DEFAULT);
                    break;
            }

            mIV = IV_DEFAULT;

            // Generate Key
            //mSymmetricAlgorithm.GenerateKey();

            // Generate IV
            //mSymmetricAlgorithm.GenerateIV();
        }
        #endregion

        #region "Misc Public Methods"

        /*
		public string generateKey()
		{
			mSymmetricAlgorithm.GenerateKey();

			return Convert.ToBase64String(mSymmetricAlgorithm.Key);
		}

		public string generateIV()
		{
			mSymmetricAlgorithm.GenerateIV();

			return Convert.ToBase64String(mSymmetricAlgorithm.IV);
		}
		*/

        #endregion
    }
}